home *** CD-ROM | disk | FTP | other *** search
- /*
- Copyright Cornell University 1986. All rights are reserved.
- */
-
-
- /***************************************************************************
- ** 3270 Driver initializations, main program, & error handler **
- ****************************************************************************
- ** Developed at Cornell University by: **
- ** Richard Cogger, Peter Hoyt, Kevin Saunders, & John Lynn **
- ** includes calls to TCP, IP, and tasking routines developed at MIT **
- ***************************************************************************/
-
- /* tn3270.c contains the main() loop and various support routines */
-
- #ifdef MULTI
- /* multiple windows version */
-
- #include <em.h>
-
- #include <cntl.h>
- #include <key.h>
- #include <macdefs.h>
- #include <h19.h>
- #include <timer.h>
- #include <ft.h>
-
- #include <3270.h> /* external variables & constants */
- #include <cntldefs.h>
- #include <resdefs.h>
- #include "xlate.h"
- #include "menudefs.h"
- #include "tftp.h"
-
- #ifdef DUALTCP
-
- #include <net.h> /* NEW merged TCP drags in task.h */
- #else
-
- #include <net.h> /* NEW merged TCP drags in task.h */
- #include <q.h> /* TODO should be different with MACTCP alone */
- extern char timertripped; /* the timer requires service */
- #endif
-
- #else
-
- #ifdef MACTCP
- #include <q.h>
- #else
- #include <tcp.h>
-
- #endif
-
- #include <stdio.h>
-
- #include <osutil.h>
- #include <quickdraw.h>
- #include <resource.h>
- #include <toolutil.h>
- #include <window.h>
- #include <control.h>
- #include <font.h>
- #include <event.h>
- #include <desk.h>
- #include <packages.h>
- #include <segment.h>
-
- #include <menu.h>
- #include <dialog.h>
- #include <memory.h>
-
- #include <cntl.h>
- #include <key.h>
- #include <macdefs.h>
- #include <h19.h>
- #include <timer.h>
- #include <emdefs.h>
- #include <telnet.h>
- #include <ft.h>
-
- #include <3270.h> /* external variables & constants */
- #include <cntldefs.h>
- #include <resdefs.h>
- #include "xlate.h"
- #include "menudefs.h"
- #include "tftp.h"
-
- #endif
-
-
-
- #ifdef DUALTCP
- #undef MACTCP
- /* make both tcps in one package */
- #endif
-
-
- struct winds * conns[MAXWIND];
- short conncount;
-
- /* true globals */
-
- #ifdef MULTI
- struct winds * emdp; /* pointer to connection block we're using */
- struct winds * keydp; /* pointer to top window connection block we're using */
- #endif
-
- short mfbackonly; /* run whole app only in background */
-
- WindowPtr keywindow; /* the active window, emwindow or textwindow */
- WindowPtr iconwindow; /* top go-away window, shows tn3270 icon */
- WindowPtr emwindow; /* the current output emulator window */
-
- #ifdef USEHELPWINDOW
- /* help window vars */
- WindowPtr helpwindow; /* there is one help window */
- struct windtext helptext;
- struct windtext {
- TEHandle texthand; /* with a TextEdit box and a scrollbar */
- int FirstLine; /* the number of the line at the top */
- short textscrapped; /* the TE scrap has been touched and must be coerced */
- short textlines; /* # of lines in page */
- ControlHandle scrollhand; /* scroll bar control */
- }
- #endif
-
- EventRecord myEvent;
-
- short courierprint; /* print using Courier on LaserWriters? */
- short appresfid; /* application resource file descriptor */
- short appvol; /* application home volume */
- long appdir; /* application home directory */
- short appvref; /* application volume ref num */
-
- char * setfile = "\PComet Default"; /* system folder settings default filename */
-
- short quitonclose; /* user wants app to close when no windows */
-
- /* connection management */
- short connavailable; /* an empty connection struct is lying about */
-
- /* TCP vars */
- short cutcpopen; /* Cornell TCP has been opened */
- short macipopen; /* macTCP has been opened */
- short mactcpopen; /* macTCP has been opened */
- short mtevent; /* MacTCP--new data or control info has arrived */
-
- short mtcpsendasync; /* use async send w/ MacTCP */
-
- short tftpopen; /* has tftp been initialized? */
- short tftpserve; /* act as a tftp server */
- short tftpask; /* query user about transfers */
-
- short trydsdraw; /* *try* to use direct to screen drawing */
- short riskydsdraw; /* only use dsdraw in FrontWindow() */
-
- PicHandle shrinkpict; /* picture for shrink control */
- PicHandle tapepict; /* picture of cassette tape */
-
- short icon_up; /* iconwindow is up for top window */
-
- long long1; /* useful storage for assembly routines */
- long long2;
- long long3;
- long long4;
-
- TEHandle helptehand;
- WindowPtr helpwind;
- long filltimeout;
-
- /* mouserect sizing and tracking of cursor */
-
- short trackon; /* flag for cursor tracking on */
- Rect mouserect; /* also used by h19curset to find the targeted x,y */
- short inemulator; /* an emulator is in use */
- short clickdelay = 10; /* # of ticks to wait before setting a selection */
-
- /* Cursors */
-
- Rect cursrect; /* inviolable cursor Rect */
- short curson; /* cursor state on or off */
- Cursor blank = {
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 8, 8 };
- Cursor * thecursor = ␣
- Rect zaprect; /* for ShieldCursor */
- SysPtr paramptr; /* pointer to parameters for cursor blink time */
- unsigned long cursalarm; /* tick count at which to change cursor */
- RgnHandle emclip; /* holds previous em clip rect */
- RgnHandle q3clip; /* for calculating new clip w/o q3 box */
-
-
- /* q3 control globals */
- short q3conth; /* height of quadrant 3 control button */
- short q3contskip; /* size of skip every 3 buttons */
- Rect boxrect; /* box in which the q3 button labels are drawn */
-
- /* character images for direct to screen drawing */
-
- FONTS font; /* normal font */
- FONTS invfont; /* inverted */
- FONTS boldfont; /* bold font */
- FONTS invboldfont; /* inverted */
- FONTS bvtfont; /* vt font */
- FONTS invbvtfont; /* inverted */
-
- short * chofftab9; /* array of character offsets to avoid multiplies */
- short * chofftab12; /* array of character offsets to avoid multiplies */
-
- RgnHandle updateRgn; /* rgn for scroll update regions */
-
- short bkrd_act = 1; /* is tcp running in background mode? */
-
- Rect dragrect; /* the drag rectangle for all windows */
-
- /* we use a bit array to mark dirty lines a` la zapchar, here are the masks */
-
- unsigned long modmask[32] = {
- 0x00000001L,
- 0x00000002L,
- 0x00000004L,
- 0x00000008L,
- 0x00000010L,
- 0x00000020L,
- 0x00000040L,
- 0x00000080L,
- 0x00000100L,
- 0x00000200L,
- 0x00000400L,
- 0x00000800L,
- 0x00001000L,
- 0x00002000L,
- 0x00004000L,
- 0x00008000L,
- 0x00010000L,
- 0x00020000L,
- 0x00040000L,
- 0x00080000L,
- 0x00100000L,
- 0x00200000L,
- 0x00400000L,
- 0x00800000L,
- 0x01000000L,
- 0x02000000L,
- 0x04000000L,
- 0x08000000L,
- 0x10000000L,
- 0x20000000L,
- 0x40000000L,
- 0x80000000L
- };
-
- char zapuline; /* flag to zapchar to underline character */
- char zapinvert; /* flag to zapchar to underline character */
-
- char inselection; /* flag that we are in selection range */
-
- char skiparr[NOCHARS]; /* chars which are blank & can be skipped */
- char allskiparr[NOCHARS]; /* alternate all-TRUE skiparr */
-
- short keyboard = PLUSKEYBOARD; /* keyboard type */
- short keypadswitch; /* switch SE keypad */
-
- /* a default ibmcolormap */
-
- struct ibmcolormap ibmcolormap = {
- /* unprotected ... */
- 0, 0, 0, 65535, 65535, 65535, /* normal (black on white) */
- 50000, 1000, 1000, 65535, 65535, 65535, /* sense (red on white) */
- 0, 0, 0, 65535, 65535, 65535, /* intense (black on white) */
- 0, 0, 0, 65535, 65535, 65535, /* invis (black on white) */
-
- /* protected ... */
- 0, 0, 0, 65535, 65535, 65535, /* normal (black on white) */
- 50000, 1000, 1000, 65535, 65535, 65535, /* sense (red on white) */
- 0, 0, 0, 65535, 65535, 65535, /* intense (black on white) */
- 0, 0, 0, 65535, 65535, 65535 /* invis (black on white) */
- };
-
- struct ibmcolormap asccolormap = {
- 0x0000, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, /* normal (black on white) */
- 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, /* reverse (white on black) */
- 0xFFFF, 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, /* bold (red on white) */
- 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0x0000, 0x0000, /* bold reverse (white on red) */
-
- /* blink ... */
- 0x0000, 0x0000, 0x0000, 0xFF70, 0xFFFF, 0x3752, /* black on yellow */
- 0xFF70, 0xFFFF, 0x3752, 0x0000, 0x0000, 0x0000, /* rev: Yellow on black */
- 0xFFFF, 0x0000, 0x0000, 0xFF70, 0xFFFF, 0x3752, /* bold: red on yellow */
- 0xFF70, 0xFFFF, 0x3752, 0xFFFF, 0x0000, 0x0000, /* boldrev: yellow on red */
- };
-
- /* TODO ideally the strings and actions associated with the 3rd quadrant buttons
- would be reconfigurable on a per-window basis... */
-
- char * q3strings[] = {
- "PF1",
- "PF2",
- "PF3",
- "PF4",
- "PF5",
- "PF6",
- "PF7",
- "PF8",
- "PF9",
- "PF10",
- "PF11",
- "PF12",
- "PF13",
- "PF14",
- "PF15",
- "PF16",
- "PF17",
- "PF18",
- "PF19",
- "PF20",
- "PF21",
- "PF22",
- "PF23",
- "PF24",
-
- /* VT52/VT100 labels */
- "KP 1",
- "KP 2",
- "KP 3",
- "KP 4",
- "KP 5",
- "KP 6",
- "KP 7",
- "KP 8",
- "KP 9",
- "KP 0",
- "KP -",
- "KP , (+)",
-
- "PF1 (Gold)",
- "PF2 (Help)",
- "PF3",
- "PF4",
- "KP .",
- "KP Enter",
- "Find",
- "Insert Here",
- "Remove",
- "Select",
- "Prev Screen",
- "Next Screen"
- };
-
- /* for ASCII vt100 mode */
-
- char q3vtcontrols[] = {
- 'q',
- 'r',
- 's',
- 't',
- 'u',
- 'v',
- 'w',
- 'x',
- 'y',
- 'p',
- 'm',
- 'l',
-
- 'P',
- 'Q',
- 'R',
- 'S',
- 'n',
- 'M',
- '1',
- '2',
- '3',
- '4',
- '5',
- '6'
- };
-
- /* for ASCII mode */
-
- char q3controls[] = {
- 'S',
- 'T',
- 'U',
- 'V',
- 'W',
- 'X',
- 'Y',
- 'Z',
- '[',
- 'P',
- 'Q',
- 'R'
- };
-
- char * nosessionstr = "Session closed";
- char * hostwait = "Connecting to host...";
- char * badaddress = "Invalid host address";
-
-
- /* BIGG preserve as globals for better speed */
-
- /* shared BIGG */
-
- /* used by dsdraw zap.asm routines */
-
- FONTS *thefont; /* BIGG */
- short xpos, ypos; /* BIGG current x, y position */
- unsigned long modflg; /* BIGG line modified bit array */
- unsigned long clrflg; /* BIGG line cleared bit array */
- short fontwidth; /* BIGG width of font */
- short ** startarr; /* BIGG dsdraw -> array of ptrs to scanline starts */
- short screenbytes; /* BIGG width of screen in bytes */
- short screenrem; /* BIGG screenbytes - std screen */
- char * skiptest; /* current skip array to use in zap */
-
- /* h19 BIGG */
- short mode; /* BIGG interpretation mode of emulator */
- unsigned char * charp; /* BIGG cursor loc for these arrays */
- short inserton; /* BIGG insert mode */
- short linelength; /* BIGG width of row */
- short lastcol; /* BIGG linelength - 1 */
- unsigned char attrib; /* BIGG normal/reverse mode for copy drawing */
-
- short wrap_around; /* BIGG wrap at end of line if true */
-
- /* vt100 BIGG */
-
- short vtmode; /* BIGG new mode holder for vt100 */
- unsigned short * argp; /* BIGG -> current argument */
-
- /* 3270 BIGG */
- short cmdstate; /* BIGG state of the emulator */
- unsigned char *scr_map; /* BIGG screen map */
- unsigned char *smap_end; /* BIGG end of map */
- unsigned char *current_attr; /* BIGG pointer to most recent attribute */
- unsigned char *cursor_ptr; /* BIGG current cursor position in screen map */
- unsigned char * firstp; /* BIGG ptr to first data byte processed for set_map */
-
-
-
-
- /* end BIGG vars */
-
-
-
- #ifdef MACTCP
- unsigned NDEBUG = TRUE; /* stupid debug flag */
- struct net thisnet;
- struct net * rnet;
- short nnrup; /* network not responding dialog up */
- struct task * tk_cur; /* subs for current task ptr */
- short iplog;
-
- extern int tcpwr_usr(); /* these are now stubs for compatibility */
- extern int tcpmst_run();
- extern int tcpopn_usr();
- extern int tcpcls_usr();
- extern int tcptmo_usr();
- extern int tcppr_dot();
- extern int tcpbfr();
-
- #else
-
- extern int tcpwr_usr();
- extern int tcpmst_run();
- extern int tcpopn_usr();
- extern int tcpcls_usr();
- extern int tcptmo_usr();
- extern int tcppr_dot();
- extern int tcpbfr();
- #endif
-
-
- unsigned long tickserial; /* next tick count to service serial port */
- short serialwait; /* how long the serial mgr thinks we should wait */
- unsigned long tickcursor; /* next tick count to service cursor */
- unsigned long tickstats; /* next tick count to display packet counters */
- extern short modaldialog;
-
-
- int proc_token();
- int nullputchar();
- int nullputflush();
-
- short edresetselect; /* reset selection after emulator edit action */
-
- char isdiacritic[NOCHARS]; /* marks 0-width diacritical characters for screen drawing */
-
-
- /* NEW CU TCP/ MacTCP merge features */
-
- struct winds * tcpemdp; /* the window context in which CU tcp runs */
-
-
-
- #ifdef KEEPALIVE
-
- timer *tel_ayt;
- #define AYTT 500 /* seconds between ayt tickles */
- extern int beep_ayt();
-
- #endif
-
-
-
-
- main()
- {
- #ifdef MACTCP
- rnet = &thisnet;
- #else
- #asm
- public _appstak
- move.l a6,_appstak ; /* set the stack bottom ptr to copy the whole stack */
- #endasm
- #endif
-
- A5init(); /* save a5 */
- macinit((long) (75L * 1024L));
- setupapplemenu(); /* so we can chk for multifinder */
- if (chkmultifinder()) {
- EventRecord myEvent;
-
- /* eventavail will put these back on the queue, but not just any event! */
- EventAvail(keyDownMask, &myEvent);
- EventAvail(keyDownMask, &myEvent);
- EventAvail(keyDownMask, &myEvent);
- /* these calls will prompt the MultiFinder to display our startup screen */
- }
- if (!scrinit()) {
- error("Can't initialize screen");
- cu_exit(-1);
- }
-
- tn_init();
- ibm_init();
- setupmenu();
-
- SetEventMask(everyEvent);
- /* fix event mask for autokeycommand--may cause full event queue! */
-
- #ifdef DOHYC
- hyc_init();
- #endif
-
- /* and some optional stuff */
-
- #ifdef KEEPALIVE
- if ((tel_ayt = tm_alloc()) == NULL) {
- error("Unable to allocate telnet ayt timer");
- cu_exit(-1);
- }
- tm_set(AYTT, beep_ayt, NULL, tel_ayt);
- #endif
-
- #ifdef MACTCP
- tk_cur = 2L; /* needs to be nonzero so tk_yield will be called */
- tm_init();
- #else
- /* initialize tasking */
- tk_init(10000); /* size of the main task's stack */
- tm_init();
- #endif
-
- /* open document files & do configuration */
- openlaunchres();
-
- fillwindclose();
- /* close the copyright window if it's up */
-
- #ifdef TFTPSERVE
- /* start the tftp server and turn it on if configured on */
- if (tftpserve == TFYES) {
- tfs_on();
- }
- #endif
- /* and now we run ... */
- while (TRUE) {
-
- user_act(); /* user input--process mac events */
-
- token_service(); /* user output--handle actions waiting on the queue */
- io_service(); /* for merged MacTCP/CUTCP */
- screen_service(); /* update screen */
-
- #ifdef DUALTCP
- tk_yield(); /* task yield for Cornell TCP */
- #else
- if (timertripped)
- tm_main(); /* service timer */
- #endif
- }
- /* not reached */
- cu_exit(0);
- }
-
-
- /* some trivial subroutines that interact with lower level code */
-
- #ifdef KEEPALIVE
-
- /* set a flag when timer pops (should just send an AYT!) */
-
- beep_ayt()
- {
- emdp->event_reg |= TICKLE;
- }
-
- #endif
-
- /* figure out a neat telnet socket */
-
- tn_sock()
- {
- long temp;
-
- GetDateTime(&temp);
- temp &= 0xffff;
- if (temp < 1000)
- temp += 1000;
- return((unsigned) temp);
- }
-
-
- /* called when a connection is opened to perform UI tasks */
-
- opn_usr()
- {
- emdp->connopen = TRUE;
-
- emdp->hycconnwait = FALSE;
- if (emdp->emwindow != NULL) {
- /* update the menus; first the window menu mark */
- if (emdp->conntype == CONN_MACTCP || emdp->conntype == CONN_CUTCP) {
- windmenumark(emdp, 0xA5); /* set a • mark */
- }
- else if (emdp->conntype == CONN_SERD) {
- windmenumark(emdp, emdp->usebport ? '-' : '+');
- /* set a mark on the menu item + for modem port,
- - for printer port */
- }
- else if (emdp->conntype == CONN_COMMMGR) {
- windmenumark(emdp, 0xA5); /* set a • mark */
- }
-
- if (keydp == NULL || emwindow == keydp->emwindow) {
- if (setmsession(emdp) || setmenuconn(emdp))
- DrawMenuBar();
- }
- restore25(); /* allow controls to be drawn */
- }
- }
-
-
- /* called when a session is closed, window menu mark already set */
- /* WARNING: twp may disappear, emdp may change! */
-
-
- cls_usr()
- {
- if (!emdp->connopen)
- return;
-
- if (emdp->hycactive)
- emdp->hycconnwait = FALSE;
-
- emdp->connopen = FALSE;
- emdp->termset = FALSE; /* no terminal type selected */
- emdp->event_reg = 0;
- emdp->in_cnt = 0;
- emdp->out_cnt = 0;
- flushactions(emdp);
-
- savescreen(); /* in case we're logging the session */
- logclose();
-
- if (emdp->emwindow != NULL) {
-
- if (!line25on(emdp))
- pr25(0, nosessionstr);
- status_info();
- /* prettywind(TRUE);
- results in cleared area when color is on */
- if (keydp == NULL || emdp->emwindow == keydp->emwindow) {
- /* fix menu to reflect status */
- if (setmsession(emdp) || setmenuconn(emdp))
- DrawMenuBar();
- }
- if (emdp->disposeonclose) {
- /* kill window when closed */
- queryclosewind(emdp);
- }
- }
- }
-
- tcpmst_run()
- {
- }
-
-
- /* call wr_usr after getting the context */
-
- tcpwr_usr(buf, len, urg)
- unsigned char *buf;
- int len;
- int urg;
- {
- struct winds * oemdp;
-
- oemdp = emdp;
- getcontext(tcpemdp);
- wr_usr(buf, len, urg);
-
- if (emdp == oemdp)
- emdp->modflg = modflg;
- /* needs to be updated even if no context change so screen_service can
- pick up the changes */
- else
- getcontext(oemdp);
- }
-
- /* call opn_usr after getting the context */
-
- tcpopn_usr()
- {
- struct winds * oemdp;
-
- oemdp = emdp;
- getcontext(tcpemdp);
- opn_usr();
- getcontext(oemdp);
- }
-
- /* call cls_usr after getting the context */
-
- tcpcls_usr()
- {
- struct winds * oemdp;
-
- tcpemdp->closeflag = TRUE;
- mtevent = TRUE;
- }
-
-
- /* make a new connection, do user dialog to configure it, and connect */
-
- newconn()
- {
- if (makeconn())
- return(-1);
-
- opensettings();
- getconfig(); /* do first, namewindow response may override */
- releaseconfig(); /* release handles, which we don't want to use */
-
- if (namewindow()) {
- closesettings();
- killconn();
- return(-1);
- }
-
- emdp->newconf = TRUE;
- /* it's a new, unopened file even if "Untitled" unchanged */
-
- setappfilename();
-
- if (makewind()) {
- closesettings();
- killconn();
- return(-1);
- }
-
- emdp->resfid = 0;
- setwindvols(emdp); /* set default directories */
-
- closesettings();
-
- emdp->keyxhead = NULL; /* don't inherit key resources */
-
- restore25();
- addwindmenu(emdp->emwindow);
-
- openconn(emdp);
-
- return(0);
- }
-
-
- /* make a new connection structure, initialize vt100 */
-
- makeconn()
- {
- struct winds * otwp;
- struct timer * otimer;
-
- if (conncount >= MAXWIND)
- return(-1);
-
- if (connavailable) {
- /* emdp is the only connection block lying around,
- no window, no connection */
- connavailable = FALSE;
- emedit(emdp, TRUE);
-
- /* save things from the old structure */
- otimer = emdp->token_tm;
- memzero(emdp, sizeof(struct winds));
- /* zero out the new structure */
- emdp->token_tm = otimer;
- }
- else {
- if (!memtest((long) sizeof(struct winds), "to make session")) {
- return(-1);
- }
- otwp = emdp;
- savecontext(emdp);
- emdp = NewPtr((Size) (sizeof(struct winds)));
- if (emdp == NULL) {
- emdp = otwp;
- return(-1);
- }
- memzero(emdp, sizeof(struct winds));
- /* zero out the new structure */
-
- setcontext(emdp);
-
- if ((emdp->token_tm = tm_alloc()) == NULL) {
- DisposPtr(emdp);
- getcontext(otwp);
- return(-1);
- }
- }
-
- emdp->emwindow = (WindowPtr) NULL;
- emdp->iconwindow = (WindowPtr) NULL;
-
- emdp->savefid = 0;
- emdp->gotoy = -1;
-
- emdp->cursorwait = TRUE;
- ibmmode(FALSE);
-
- emdp->putchar = nullputchar;
- emdp->putflush = nullputflush;
- conns[conncount] = emdp;
- conncount++;
-
- return(0);
-
- }
-
- /* destroy the most recent attempt to make a connection structure */
-
- killconn()
- {
- --conncount;
- conns[conncount] = NULL;
- if (keydp != NULL) {
- DisposPtr(emdp);
- setcontext(keydp);
- }
- else {
- setcontext(conns[0]);
- }
- }
-
-
- /* standard close bottleneck call */
-
- closeconn(twp)
- struct winds * twp;
- {
- if (twp->connopen) {
- getcontext(twp);
- if (!hostclosemacro(twp->closemacro))
- /* if there's no close macro, go ahead and close it up */
- docloseconn();
- }
- }
-
- /* REALLY do a close on the emdp connection */
-
- docloseconn()
- {
- if (!emdp->connopen) {
- return();
- }
- if (emdp->conntype == CONN_MACTCP) {
- mactcp_close();
- }
- #ifdef DUALTCP
- else if (emdp->conntype == CONN_CUTCP) {
- tcp_close();
- emdp->ucb.u_state = CLOSING;
- emdp->ucb.u_rstate = BLOCK;
- }
- #endif
- else if (emdp->conntype == CONN_SERD) {
- windmenumark(emdp, noMark); /* clear any marks */
- closeserport(emdp);
- cls_usr(); /* WARNING: twp may disappear, emdp may change! */
- }
- }
-
-
- /* remove a connection from the table, we have no connection */
-
- releaseconn(twp)
- struct winds * twp;
- {
- register short count = 0;
-
- for (count = 0; count < conncount; count ++) {
- if (twp == conns[count])
- break;
- }
- if (count == conncount)
- /* no such connection exists */
- return(-1);
-
- /* we found a match, release resources associated with it */
- if (twp->conntype == CONN_MACTCP) {
- if (mactcpopen) {
- tcp_release(twp);
- tcpmemoryreclaim(twp);
- }
- }
- #ifdef DUALTCP
- else if (twp->conntype == CONN_CUTCP) {
- if (cutcpopen) {
- /* TODO should we close down Cornell TCP completely to
- allow MacTCP to run? */
- /* tcpemdp = NULL; TODO this is improper! */
- ;
- }
- }
- #endif
- else if (twp->conntype == CONN_SERD) {
- closeserport(twp);
- }
-
-
- if (conncount > 1) {
- /* kill it */
-
- ascii_free(twp); /* release any ASCII emulator memory */
- ibm_free(twp); /* release any IBM emulator memory */
- tm_clear(twp->token_tm);
- tm_free(twp->token_tm);
- DisposPtr(twp);
-
- /* now shift down the other conns in the table */
- for ( count++ ; count < conncount; count++) {
- conns[count - 1] = conns[count];
- }
-
- /* set the context to the first one */
- if (twp == emdp ) {
- /* the current context has been devastated */
- emdp = NULL;
- getcontext(conns[0]); /* set context to the first one in the table */
- }
- if (twp == keydp) {
- /* if the context was the one on top--very likely--
- it exists no longer... */
- keydp = NULL;
- keywindow = NULL;
- }
- }
- else {
- /* leave one emdp struct around so
- only 1 conn struct w/ no window exists */
-
- if (quitonclose)
- /* user wants close when no windows/sessions exist */
- cu_exit(0);
-
- connavailable = TRUE;
- setcontext(emdp);
-
- keydp = NULL;
- keywindow = NULL;
-
- emedit(emdp, TRUE);
- showcursor(); /* make sure cursor drawn */
- /* TODO windows need to be reset and should the config be reset? */
- }
- --conncount;
- conns[conncount] = NULL;
- }
-
-
- /* open a connection for a connection/window structure
- must be in emdp context (using getcontext() or makeconn() )
- */
-
- openconn(twp)
- struct winds * twp;
- {
- unsigned sock;
-
- #ifdef ARPFORHOST
- if (!at_arp(fhost.u.addr))
- return(-2);
- #endif
-
- if (twp->connopen)
- return;
-
- #ifdef MACTCP
- if (twp->conntype == CONN_CUTCP) {
- /* force it */
- twp->conntype = CONN_MACTCP;
- }
- #endif
-
- if (twp->emwindow) {
- /* fix the window and menu */
- windmenumark(twp, noMark); /* clear any marks */
- restore25();
- }
-
- if (twp->conntype == CONN_MACTCP
- || twp->conntype == CONN_CUTCP) {
- telnetreset(twp->termtype);
- }
-
- if (twp->conntype == CONN_MACTCP
- || macipopen && twp->conntype == CONN_CUTCP) {
- /* coerce MacTCP configuration if Cornell already started */
-
- extern int mactcp_put();
- extern int mactcp_ex();
-
- twp->conntype = CONN_MACTCP;
-
- twp->putchar = mactcp_put;
- twp->putflush = mactcp_ex;
-
- sock = tn_sock();
- if (twp->fhost.u.addr == -1L
- || twp->fhost.u.addr == 0L) {
- /* avoid opening sessions to broadcast address, can
- induce Cornell AT-GW to produce telnet storms... */
- error("Can't open Telnet session to the broadcast address; please reconfigure the session address");
- }
- else {
- pr25(0, hostwait);
- mactcp_open(&twp->fhost.u.addr, twp->fhost.port, sock);
- }
- }
- #ifdef DUALTCP
- else if (twp->conntype == CONN_CUTCP) {
- extern int tc_put();
- extern int tcp_ex();
-
- if (tcpemdp == NULL) {
- /* add gateway address slot */
- tcpmenu();
- }
- else {
- if (tcpemdp->connopen) {
- error("Only one Cornell TCP session can be used at a time");
- return(-1);
- }
- }
-
- pr25(0, hostwait);
- twp->putchar = tc_put;
- twp->putflush = tcp_ex;
-
- tcpemdp = twp;
- if (!cutcpopen) {
- if (opensettings())
- error("Can't open 'Comet Default' document");
-
-
- tcp_init(0, tcpopn_usr, tcpwr_usr, tcpmst_run,
- tcpcls_usr, tcptmo_usr, tcppr_dot, tcpbfr);
-
- cutcpopen = TRUE;
- if (! (*rnet->n_subnet)()) {
- if (get_subnet()) {
- /* ignore lack of gateway, assume local net */
- ;
- }
- else {
- closesettings();
- return(-1);
- }
- }
- closesettings();
- }
- sock = tn_sock();
- tcp_open(&twp->fhost.u.addr, twp->fhost.port, sock);
- }
- #endif
- else if (twp->conntype == CONN_SERD) {
- extern int serputchar();
- extern int serputflush();
-
- twp->putchar = serputchar;
- twp->putflush = serputflush;
-
- termreset(); /* clear the old screen */
- gettermtype();
- setcontext(emdp);
-
- setibm_keymode(twp->ibm_keymode);
- /* get controls now, whereas Telnet must wait until negotiations cease */
-
- if (openserport()) {
- pr25(0, nosessionstr);
- return(-1);
- }
- opn_usr();
- emdp->tndata = TRUE; /* guarantee controls come up */
- hostconncomplete(emdp->connmacro);
- }
- return(0);
- }
-
-
-
- #define DLACCEPT 2000
- #define DLACYES 1
- #define DLACNO 2
-
- int tftp_direction;
-
- tntftp(host, file, dir)
- in_name host;
- char *file;
- unsigned dir;
- {
- char buffer[100];
- char c;
- short item;
- DialogPtr dptr;
- GrafPtr oldport;
-
- tftp_direction = dir;
- if (tftpask == TFNO) {
- mac_setdownvol();
- if (dir == PUT) {
- /* save the text window if necessary */
- textupedit(file);
- }
- return(TRUE);
- }
- else if (tftpask == TFYES) {
- #ifdef BACKTFTPREJECT
- if (chkbackground())
- /* if asking on & we're in the background, reject the request */
- return(FALSE);
- #endif
-
- if (host == emdp->fhost.u.addr) {
- ctop(file);
- HLock(emdp->hhostname);
- ParamText(*emdp->hhostname, dir == PUT ? "\Pread" : "\Pwrite", file, "\P");
- HUnlock(emdp->hhostname);
- ptoc(file);
- }
- else {
- sprintf(buffer, "%a", host);
- ctop(buffer);
- ctop(file);
- ParamText(buffer, dir == PUT ? "\Pread" : "\Pwrite", file, "\P");
- ptoc(file);
- }
- /* do dialog to determine if user will accept */
- GetPort(&oldport);
- emwdeactivate();
-
- SetDAFont(systemFont);
- if ( ( dptr =
- GetNewDialog(DLACCEPT, (Ptr) NULL, (WindowPtr) -1) ) == NULL )
- return(FALSE);
-
- centerwind(dptr);
- SetPort(dptr);
- SetCursor(&arrow); /* guarantee cursor is not blank */
- itemhighlight(dptr, 1);
-
- modaldialog = TRUE;
- while (TRUE) {
- #ifdef MACTCP
- ModalDialog( (ProcPtr) NULL, &item);
- #else
- extern Boolean alfilter();
- ModalDialog( (ProcPtr) alfilter, &item);
- #endif
- switch (item) {
- case DLACYES: {
- DisposDialog(dptr);
- SetPort(oldport);
- modaldialog = FALSE;
- mac_setdownvol(); /* fix the directory for multiple sessions */
- if (dir == PUT)
- textupedit(file);
- return(TRUE);
- }
- case DLACNO: {
- DisposDialog(dptr);
- SetPort(oldport);
- modaldialog = FALSE;
- return(FALSE);
- }
- }
- }
- }
- }
-
-
-
-
- /* function called when file transfer is done. */
-
- #define ALFTOK 2001
- #define ALFTFAIL 2002
-
- char transok[] = "File transferred OK\r";
- char transfail[] = "File transfer FAILED\r";
-
- tntfdn(success)
- int success;
- {
- extern char macfile[]; /* for tftp Macintosh file name translation */
-
- if (success) {
- if (tftp_direction == GET) {
- textdownedit(&macfile[0]);
- }
- }
- else {
- fillwindow(COPYWINDOW, transfail, (long) strlen(transfail), systemFont, 12, 0L);
- }
- }
-
-
-
- itemhighlight(dlog, item)
- DialogPtr dlog;
- int item;
- {
- short itemtype;
- Handle itemhand;
- Rect itemrect;
-
- GetDItem(dlog, (short) item, &itemtype, &itemhand, &itemrect);
- PenSize(3, 3);
- InsetRect(&itemrect, -4, -4);
- FrameRoundRect(&itemrect, 16, 16);
- }
-
- /* check to see if we have enough memory */
-
- char * memstr = "Not enough memory ";
-
- long memtest(amount, usererr)
- long amount;
- char * usererr;
- {
- long free;
- char errstr[120];
- char * errp;
-
- if ( (free = FreeMem()) < amount + 15000) {
- strcpy(&errstr[0], memstr);
- if (usererr != NULL)
- strncat(&errstr[strlen(memstr)], usererr, 80);
- prerr25(&errstr[0]);
- return(0);
- }
- else
- return(free);
- }
-
-
-
- #ifdef MACTCP
- /* define stubs for uncalled functions */
-
- tcptmo_usr()
- {
- }
-
-
- tcpbfr()
- {
- }
-
- tcppr_dot()
- {
- }
-
-
- datayield()
- {
- }
-
- #else
- tcptmo_usr()
- {
- error("Cannot reach host");
- tcpemdp->closeflag = TRUE;
- mtevent = TRUE;
- }
-
-
- tcpbfr()
- {
- if (tcpemdp->ucb.u_tcpfull) {
- tcpemdp->ucb.u_tcpfull = 0;
- }
- }
-
- tcppr_dot()
- {
- }
-
-
- datayield()
- {
- if (rnet->n_demux->ev_flg) {
- /* input q needs service */
- tkrun = rnet->n_demux;
- tk_yield();
- }
- }
-
- #endif
-
- /* change controls & menus to reflect terminal we are emulating */
-
- ibmmode(flag)
- int flag;
- {
- extern int ibmproc_token();
- extern int ibmsendchar();
- extern int ibmsendstr();
-
- extern int proc_token();
- extern int asciisendchar();
- extern int asciisendstr();
-
- emdp->ibm_mode = flag;
-
- /* select the token processor for handling user input */
- if (emdp->ibm_mode) {
- emdp->dotoken = ibmproc_token;
- emdp->sendchar = ibmsendchar;
- emdp->sendstr = ibmsendstr;
-
- /* TODO we need to reset the color map if it wasn't configured ... */
- }
- else {
- emdp->dotoken = proc_token;
- emdp->sendchar = asciisendchar;
- emdp->sendstr = asciisendstr;
- }
- }
-
-
- /* set up the controls and key resources for the emulator type
- TODO could be more efficient if already set...
- */
-
- setibm_keymode(flag)
- int flag;
- {
- /* fix controls */
-
- reopenconfig(emdp);
-
- if (emwindow != NULL) {
- killcontrols(emwindow);
- controlinit(emwindow, flag ? IBMRES : ASCRES);
-
- /* do menu stuff */
- if (emdp == keydp) {
- if (keymenus(emdp))
- DrawMenuBar();
- }
- }
-
- /* fix the key resources */
- keyxrelease();
- if (!emdp->newconf)
- keyxinit();
- closeconfig(emdp);
- }
-
-
-
- #define MAXCLOSERS 30
- static int (*closers[MAXCLOSERS])();
- static int nclosers = 0;
-
- exit_hook(func)
- int (*func)();
- {
- if (nclosers < MAXCLOSERS)
- closers[++nclosers] = func;
- else
- error("out of exit_hooks");
- }
-
- cu_exit(arg)
- int arg;
- {
- int count;
-
- for(count = nclosers; count; count--)
- (*closers[count])();
- exit(arg);
-
- }
-
-
- /* reset output context; most routines rely on the global emdp to
- point to the current output window. Several per-window variables
- are maintained also as globals to reduce overhead in the emulators
- and avoid modifying old code (zap esp.) to use emdp.
-
- It is crucial that the globals be maintained properly!
- */
-
- getcontext(conp)
- struct winds * conp;
- {
- if (conp == emdp) {
- /* save some time */
- if (emwindow) {
- /* guarantee at a minimum that port is set right */
- SetPort(emwindow);
- }
- return;
- }
- savecontext(emdp);
- /* save the old global context before the change */
- setcontext(conp);
- }
-
-
- /* set the globals from a winds struct; set them all, since otherwise
- there might be a failure to save stuff during Telnet negotiations */
-
- setcontext(conp)
- register struct winds * conp;
- {
- if (conp == NULL)
- return;
-
- if (conp->emwindow) {
- emwindow = conp->emwindow;
- SetPort(emwindow); /* guarantee port is set right */
- }
- else
- emwindow = NULL;
-
- emdp = conp; /* set the major league window structure * globals */
-
- thefont = conp->thefont; /* default font */
- startarr = conp->startarr; /* dsdraw -> array of ptrs to scanline starts */
- screenbytes = conp->screenbytes; /* width of screen in bytes */
- screenrem = conp->screenrem; /* screenbytes - std screen */
- fontwidth = conp->fontwidth;
-
- xpos = conp->xpos;
- ypos = conp->ypos; /* current x, y position */
- modflg = conp->modflg; /* line modified bit array */
- clrflg = conp->clrflg; /* line cleared bit array */
-
- /* H19 vars */
- mode = conp->mode; /* interpretation mode of emulator */
- charp = conp->charp; /* ASCII -> cursor location in charr */
- attrib = conp->attrib; /* normal/reverse mode for copy drawing */
-
- wrap_around = conp->wrap_around; /* normal/reverse mode for copy drawing */
- inserton = conp->inserton; /* insert mode */
- linelength = conp->linelength; /* width of row */
- lastcol = conp->lastcol; /* linelength - 1 */
-
- /* vt100; preceeding are h19 vars also */
-
- vtmode = conp->vtmode; /* new mode holder for vt100 */
- argp = conp->argp; /* -> current argument */
-
- /* variables important to the 3270 interpreter */
-
- cmdstate = conp->cmdstate; /* state of the emulator */
- scr_map = conp->scr_map; /* 3270 screen map */
- smap_end = conp->smap_end; /* end of map */
- current_attr = conp->current_attr; /* pointer to most recent attribute */
- cursor_ptr = conp->cursor_ptr; /* current cursor position in screen map */
- firstp = conp->firstp; /* ptr to first data byte processed for set_map */
- }
-
- /*
- restore output context: save the globals which may have been modified for the
- next time around with this window
- */
-
- savecontext(conp)
- register struct winds * conp;
- {
-
- if (conp == NULL)
- return;
-
- conp->xpos = xpos;
- conp->ypos = ypos; /* BIGG current x, y position */
- conp->modflg = modflg; /* BIGG line modified bit array */
- conp->clrflg = clrflg; /* BIGG line cleared bit array */
-
- /* h19 */
- conp->mode = mode; /* BIGG interpretation mode of emulator */
- conp->inserton = inserton; /* BIGG insert mode */
- conp->attrib = attrib; /* BIGG normal/reverse mode for copy drawing */
- conp->wrap_around = wrap_around; /* BIGG normal/reverse mode for copy drawing */
- conp->charp = charp; /* BIGG ASCII -> cursor location in charr */
-
- conp->linelength = linelength; /* BIGG width of row */
- conp->lastcol = lastcol; /* BIGG linelength - 1 */
-
- /* vt100 */
- conp->vtmode = vtmode; /* BIGG new mode holder for vt100 */
- conp->argp = argp; /* BIGG -> current argument */
-
- /* 3270 */
- conp->cmdstate = cmdstate; /* BIGG state of the emulator */
- conp->scr_map = scr_map; /* BIGG 3270 screen map */
- conp->smap_end = smap_end; /* BIGG end of map */
- conp->current_attr = current_attr; /* BIGG pointer to most recent attribute */
- conp->cursor_ptr = cursor_ptr; /* BIGG current cursor position in screen map */
- conp->firstp = firstp; /* BIGG ptr to first data byte processed for set_map */
-
- }
-
-
- /* We check instead to see if any data has arrived and upcall if so,
- and try to send things waiting on the queue */
-
- short inio_service;
-
- io_service()
- {
- struct winds ** conp = conns;
- struct winds * conend = &conp[conncount];
- register struct winds * twp;
- int serialtime;
-
- if (inio_service)
- return;
- inio_service = TRUE;
-
- if (tickserial && cticks >= tickserial)
- serialtime = TRUE;
- else
- serialtime = FALSE;
-
- /* go through window list to see who needs service */
- #ifdef TFTPSERVE
- if (tfsdata || tftpdata)
- /* MacTCP tftp service */
- tftp_upcall();
- #endif
-
- if (mtevent) {
- mtevent = FALSE; /* reset immediately after test: set asynchronously */
- }
- else if (serialtime) {
- tickserial = cticks + serialwait;
- }
- else {
- /* nothing happening, try to save time */
- inio_service = FALSE;
- return;
- }
-
- while (conp < conend) {
- twp = *conp++;
- if (twp == NULL)
- continue;
-
- #ifdef MAKEHYCCONN
- if (twp->hycconnwait == TRUE) {
- /* if the API has requested an open, do it */
- /* use macro ? */
- twp->hycconnwait = 1;
- if (makeconn()) {
- killconn();
- continue;
- }
- getconfig();
- emdp->resfid = appresfid;
- emdp->resvol = appvol;
- emdp->resdir = appdir;
-
- keyxinit();
- makewind();
- openconn(emdp);
- continue;
- }
- #endif
- if (twp->conntype == CONN_MACTCP) {
- /* has no new data... */
- if (! (twp->data_rcvd || twp->closeflag || twp->send_wait))
- continue;
-
- /* reset output context */
- getcontext(twp);
-
- if (twp->data_rcvd) {
- tcp_upcall();
- twp->modflg = modflg;
- /* update; could use savecontext() but not only modflg needed */
- }
- #ifdef ASYNCOPEN
- if (!modaldialog && twp->openflag) {
- opn_usr();
- }
- #endif
- if (!modaldialog && twp->closeflag) {
- /* don't EVER do this in the background, cls_usr may dialog */
- mactcp_wrapup(); /* WARNING: twp may disappear, emdp may change! */
- }
- if (twp->send_wait) {
- /* a packet is waiting for buffer; try to send again */
- mactcp_ex();
- }
- else if (twp->fillcount && (twp->fillcount == twp->waitcount)) {
- /* SHOULD NEVER REACH THIS POINT! symptom of
- MacTCP async "let's waste some variables" behavior */
- prerr25("send_wait clobbered");
- mactcp_ex();
- }
- continue;
- }
- #ifdef DUALTCP
- else if (twp->conntype == CONN_CUTCP) {
- if (!modaldialog && twp->closeflag) {
- /* close the session */
- /* don't EVER do this in the background, cls_usr may dialog */
- twp->closeflag = FALSE;
- getcontext(twp);
- windmenumark(twp, noMark); /* clear any marks */
- cls_usr(); /* WARNING: twp may disappear, emdp may change! */
- }
- continue;
- }
- #endif
- else if (twp->conntype == CONN_SERD && serialtime) {
- /* check for serial data */
-
- getcontext(twp);
- serial_service();
- twp->modflg = modflg;
- continue;
- }
- else if (twp->conntype == CONN_COMMMGR) {
- /* check for comm mgr data */
- ;
- continue;
- }
- }
- inio_service = FALSE;
- }
-
-
-
- nullputchar()
- {
- }
-
- nullputflush()
- {
- }
-
-
- /* called in the main user task to serve I/O while in dialog
- or other modal situation */
-
- bkrd_service()
- {
- struct winds * oemdp;
- GrafPtr oport;
-
- oemdp = emdp;
- GetPort(&oport);
-
- token_service(); /* user output--handle actions waiting on the queue */
- io_service(); /* for merged MacTCP/CUTCP */
- #ifdef DUALTCP
- tk_yield(); /* task yield for Cornell TCP */
- #endif
- screen_service(); /* update screen */
-
- if (emdp != oemdp)
- /* restore the old context for all the callers out there */
- getcontext(oemdp);
-
- if (oport)
- SetPort(oport); /* might not be emwindow */
- }
-
-
- /* turn the tftp server on
- */
-
- #define OFF 0
- #define ON 1
-
- tfs_on()
- {
- extern short tfstate;
-
- if (!tftpopen) {
- if (emdp->conntype == CONN_MACTCP) {
- if (mtcp_tfsinit(tntftp, tntfdn))
- return(FALSE);
- tftpopen = TRUE;
- }
- #ifdef DUALTCP
- else if (emdp->conntype == CONN_CUTCP) {
- if (tfsinit(tntftp, tntfdn))
- return(FALSE);
- tftpopen = TRUE;
- }
- #endif
- }
- tfstate = ON;
- return(TRUE);
- }
-
- /* turn the tftp server off
- */
-
- tfs_off()
- {
- extern short tfstate;
-
- tfstate = OFF;
- }
-
-
- /* set the name in the appfile struct used for document naming control */
-
- setappfilename()
- {
- register char * chp;
- register char * endp;
- register char * destp;
-
- /* copy the name into the appfile struct from hhostname;
- hhostname is a Pascal string */
- chp = *emdp->hhostname;
- endp = chp + **emdp->hhostname + 1;
- destp = &emdp->appfile.fName;
-
- while (chp < endp) {
- *destp++ = *chp++;
- }
- }
-
-
- istcptype()
- {
- if (emdp->conntype == CONN_SERD || emdp->conntype == CONN_COMMMGR)
- return(FALSE);
- else
- return(TRUE);
- }
-
-
- /* added for compatibility with MPW */
-
- SwapMMUMode(chararg)
- Byte * chararg;
- {
- #asm
- move.l 8(a6),a0 ; -> byte arg
- move.b (a0),d0 ; d0 = arg
- dc.w $a05d ; _SwapMMUMode
- move.b d0,(a0) ; return current mode in arg
- #endasm
- }
-
- #ifndef DUALTCP
-
- tcp_close()
- {
- }
-
- DialogPtr nnrdptr;
-
- shownnr()
- {
- }
-
- hidennr()
- {
- }
-
- #endif
-
-
- invalidconn(twp)
- struct winds * twp;
- {
- register short count = 0;
-
- for (count = 0; count < conncount; count++) {
- if (twp == conns[count])
- return(0);
- }
- /* no such connection exists */
- return(-1);
- }